package com.geek.novel.view.shadow

import com.geek.novel.R
import android.content.Context
import android.content.res.Resources
import android.graphics.*
import android.util.AttributeSet
import android.util.TypedValue
import android.widget.LinearLayout
import com.geek.novel.view.shadow.DimenUtil.dp2px
import kotlin.math.abs


/**
 * Created by Android Studio.
 * User: caihaifei
 * Date: 2019/9/10
 * Time: 10:27
 * WebBlog:http://www.enjoytoday.cn
 *
 * 阴影布局
 *
 */
class ShadowLayout : LinearLayout {
    //阴影颜色
    private var shadowColor = Color.parseColor("#333333")

    //阴影半径
    private var shadowRadius = 0f

    //模糊度半径
    private var blurRadius = 0f

    //水平位移
    private var xOffset = 0f

    //竖直方向位移
    private var yOffset = 0f

    //背景色
    private var bgColor = Color.WHITE

    //是否有点击效果
    private var hasEffect = false
    private var leftShadow = 0
    private var rightShadow = 0
    private var topShadow = 0
    private var bottomShadow = 0

    /**
     * 获取阴影设置
     * @return 返回阴影设置配置
     */
    private var mWidthMode = 0f
    private var mHeightMode = 0f
    private val mPaint = Paint()
    private val locationPaint = Paint()

    constructor(context: Context?) : super(context, null) {}

    @JvmOverloads
    constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int = 0) : super(context, attrs, defStyleAttr) {
        setLayerType(LAYER_TYPE_SOFTWARE, null) //取消硬件加速
        val typedArray = context.obtainStyledAttributes(attrs, R.styleable.ShadowLayout)
        shadowColor = typedArray.getColor(R.styleable.ShadowLayout_shadowColor, Color.BLUE)
        blurRadius = typedArray.getDimension(R.styleable.ShadowLayout_blurRadius, 0f)
        shadowRadius = typedArray.getDimension(R.styleable.ShadowLayout_shadowRadius, 0f)
        hasEffect = typedArray.getBoolean(R.styleable.ShadowLayout_hasEffect, false)
        xOffset = typedArray.getDimension(R.styleable.ShadowLayout_xOffset, 0f)
        yOffset = typedArray.getDimension(R.styleable.ShadowLayout_yOffset, 0f)
        bgColor = typedArray.getColor(R.styleable.ShadowLayout_bgColor, Color.WHITE)
        typedArray.recycle()
        if (shadowRadius < 0) {
            shadowRadius = -shadowRadius
        }
        if (blurRadius < 0) {
            blurRadius = -blurRadius
        }
        blurRadius = Math.min(SHADOW_MAX_BLUR, blurRadius)
        if (abs(xOffset) > SHADOW_MAX_OFFSET) {
            xOffset = xOffset / abs(xOffset) * SHADOW_MAX_OFFSET
        }
        if (abs(yOffset) > SHADOW_MAX_OFFSET) {
            yOffset = yOffset / abs(yOffset) * SHADOW_MAX_OFFSET
        }
        setBackgroundColor(Color.parseColor("#00ffffff"))
        init()
    }

    private fun init() {
        if (xOffset > 0) {
            //水平偏移量为正数，右侧有阴影，阴影长度为blurRadius+|xOffset|
            rightShadow = (blurRadius + abs(xOffset)).toInt()
        } else if (xOffset == 0f) {
            //水平偏移为0,水平间距为blurRadius
            leftShadow = blurRadius.toInt()
            rightShadow = blurRadius.toInt()
        } else {
            //水平偏移为负数,左侧有阴影，阴影长度为blurRadius+|xOffset|
            leftShadow = (blurRadius + abs(xOffset)).toInt()
        }
        if (yOffset > 0) {
            //竖直偏移量为正数，底部有阴影，阴影长度为blurRadius+|yOffset|
            bottomShadow = (blurRadius + abs(yOffset)).toInt()
        } else if (yOffset == 0f) {
            //竖直偏移量为0，竖直间距为blurRadius
            topShadow = blurRadius.toInt()
            bottomShadow = blurRadius.toInt()
        } else {
            //竖直偏移量为负数，顶部有阴影，阴影长度为blurRadius+|yOffset|
            topShadow = (blurRadius + abs(yOffset)).toInt()
        }
        setPadding(leftShadow, topShadow, rightShadow, bottomShadow)
    }

    override fun dispatchDraw(canvas: Canvas) {
        super.dispatchDraw(canvas)
    }

    override fun onDraw(canvas: Canvas) {
        drawBackground(canvas) //放在super前是后景，相反是前景，前景会覆盖子布局
    }

    //绘制背景色(在子view底部)
    private fun drawBackground(canvas: Canvas) {
        mWidthMode = measuredWidth.toFloat()
        mHeightMode = measuredHeight.toFloat()
        val startX: Float
        val startY: Float
        val endX: Float
        val endY: Float
        if (xOffset == 0f) {
            startX = rightShadow.toFloat()
            endX = mWidthMode - blurRadius
        } else {
            startX = rightShadow + blurRadius
            endX = mWidthMode - leftShadow - blurRadius
        }
        if (yOffset == 0f) {
            startY = bottomShadow.toFloat()
            endY = mHeightMode - blurRadius
        } else {
            startY = bottomShadow + blurRadius
            endY = mHeightMode - topShadow - blurRadius
        }
        //        mPaint.setShadowLayer(blurRadius,0,0,shadowColor);
        if (blurRadius > 0) {
            mPaint.maskFilter = BlurMaskFilter(blurRadius, BlurMaskFilter.Blur.NORMAL)
        }
        mPaint.color = shadowColor
        mPaint.isAntiAlias = true
        val shadowRect = RectF(startX, startY, endX, endY)
        val locationRectF = RectF(leftShadow.toFloat(), topShadow.toFloat(), mWidthMode - rightShadow, mHeightMode - bottomShadow)
        if (shadowRadius == 0f) {
            //不是圆角
            canvas.drawRect(shadowRect, mPaint)
        } else {
            //圆角，角度为shadowRadius
            canvas.drawRoundRect(shadowRect, shadowRadius, shadowRadius, mPaint)
        }
        locationPaint.color = bgColor
        locationPaint.isAntiAlias = true
        if (shadowRadius == 0f) {
            //不是圆角
            canvas.drawRect(locationRectF, locationPaint)
        } else {
            //圆角，角度为shadowRadius
            canvas.drawRoundRect(locationRectF, shadowRadius, shadowRadius, locationPaint)
        }
    }

    /**
     * 阴影配置
     */
    internal inner class ShadowConfig constructor(  //代理
        private val shadow: ShadowLayout
    ) : Shadow {
        override fun setShadowRadius(radius: Float): Shadow {
            return setShadowRadius(TypedValue.COMPLEX_UNIT_DIP, radius)
        }

        override fun setShadowRadius(unit: Int, radius: Float): Shadow {
            val c = context
            val r: Resources = if (c == null) {
                Resources.getSystem()
            } else {
                c.resources
            }
            shadow.shadowRadius = abs(TypedValue.applyDimension(unit, radius, r.displayMetrics))
            return this
        }

        override fun setShadowColor(color: Int): Shadow {
            shadow.shadowColor = color
            return this
        }

        override fun setShadowColorRes(colorRes: Int): Shadow {
            shadow.shadowColor = shadow.resources.getColor(colorRes)
            return this
        }

        override fun setBlurRadius(radius: Float): Shadow {
            return setBlurRadius(TypedValue.COMPLEX_UNIT_DIP, radius)
        }

        override fun setBlurRadius(unit: Int, radius: Float): Shadow {
            val c = context
            val r: Resources = if (c == null) {
                Resources.getSystem()
            } else {
                c.resources
            }
            shadow.blurRadius = Math.min(SHADOW_MAX_BLUR, abs(TypedValue.applyDimension(unit, radius, r.displayMetrics)))
            return this
        }

        override fun setXOffset(offset: Float): Shadow {
            return setXOffset(TypedValue.COMPLEX_UNIT_DIP, offset)
        }

        override fun setXOffset(unit: Int, offset: Float): Shadow {
            val c = context
            val r: Resources = if (c == null) {
                Resources.getSystem()
            } else {
                c.resources
            }
            var x = TypedValue.applyDimension(unit, offset, r.displayMetrics)
            if (abs(x) > SHADOW_MAX_OFFSET) {
                x = x / abs(x) * SHADOW_MAX_OFFSET
            }
            shadow.xOffset = x
            return this
        }

        override fun setYOffset(offset: Float): Shadow {
            return setYOffset(TypedValue.COMPLEX_UNIT_DIP, offset)
        }

        override fun setYOffset(unit: Int, offset: Float): Shadow {
            val c = context
            val r: Resources = if (c == null) {
                Resources.getSystem()
            } else {
                c.resources
            }
            var y = TypedValue.applyDimension(unit, offset, r.displayMetrics)
            if (abs(y) > SHADOW_MAX_OFFSET) {
                y = y / abs(y) * SHADOW_MAX_OFFSET
            }
            shadow.yOffset = y
            return this
        }

        override fun commit() {
            shadow.init()
            shadow.requestLayout()
            shadow.postInvalidate()
        }
    }

    companion object {
        //阴影最大偏移量
        val SHADOW_MAX_OFFSET = dp2px(20f)

        //阴影最大模糊半径
        val SHADOW_MAX_BLUR = dp2px(20f)

    }
}